package com.atguigu.daijia.customer.service.impl;

import com.atguigu.daijia.common.execption.GuiguException;
import com.atguigu.daijia.common.result.Result;
import com.atguigu.daijia.common.result.ResultCodeEnum;
import com.atguigu.daijia.customer.service.OrderService;
import com.atguigu.daijia.dispatch.client.NewOrderFeignClient;
import com.atguigu.daijia.driver.client.DriverInfoFeignClient;
import com.atguigu.daijia.map.client.LocationFeignClient;
import com.atguigu.daijia.map.client.MapFeignClient;
import com.atguigu.daijia.model.entity.order.OrderInfo;
import com.atguigu.daijia.model.enums.OrderStatus;
import com.atguigu.daijia.model.form.customer.ExpectOrderForm;
import com.atguigu.daijia.model.form.customer.SubmitOrderForm;
import com.atguigu.daijia.model.form.map.CalculateDrivingLineForm;
import com.atguigu.daijia.model.form.order.OrderInfoForm;
import com.atguigu.daijia.model.form.payment.CreateWxPaymentForm;
import com.atguigu.daijia.model.form.rules.FeeRuleRequestForm;
import com.atguigu.daijia.model.vo.base.PageVo;
import com.atguigu.daijia.model.vo.customer.ExpectOrderVo;
import com.atguigu.daijia.model.vo.dispatch.NewOrderTaskVo;
import com.atguigu.daijia.model.vo.driver.DriverInfoVo;
import com.atguigu.daijia.model.vo.map.DrivingLineVo;
import com.atguigu.daijia.model.vo.map.OrderLocationVo;
import com.atguigu.daijia.model.vo.map.OrderServiceLastLocationVo;
import com.atguigu.daijia.model.vo.order.CurrentOrderInfoVo;
import com.atguigu.daijia.model.vo.order.OrderBillVo;
import com.atguigu.daijia.model.vo.order.OrderInfoVo;
import com.atguigu.daijia.model.vo.payment.WxPrepayVo;
import com.atguigu.daijia.model.vo.rules.FeeRuleResponseVo;
import com.atguigu.daijia.order.client.OrderInfoFeignClient;
import com.atguigu.daijia.rules.client.FeeRuleFeignClient;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderServiceImpl implements OrderService {

    @Resource
    MapFeignClient mapFeignClient;

    @Resource
    FeeRuleFeignClient feeRuleFeignClient;

    @Resource
    OrderInfoFeignClient orderInfoFeignClient;

    @Resource
    NewOrderFeignClient newOrderFeignClient;

    @Resource
    RedisTemplate redisTemplate;

    //预估订单数据
    @Override
    public ExpectOrderVo expectOrder(ExpectOrderForm expectOrderForm) {
        //获取驾驶路线

        CalculateDrivingLineForm calculateDrivingLineForm = new CalculateDrivingLineForm();

        BeanUtils.copyProperties(expectOrderForm,calculateDrivingLineForm);

        Result<DrivingLineVo> drivingLineVoResult = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm);


        DrivingLineVo drivingLineVo = drivingLineVoResult.getData();

        //获取订单费用
        FeeRuleRequestForm feeRuleRequestForm = new FeeRuleRequestForm();

        feeRuleRequestForm.setDistance(drivingLineVo.getDistance());
        feeRuleRequestForm.setStartTime(new Date());
        feeRuleRequestForm.setWaitMinute(0);

        Result<FeeRuleResponseVo> feeRuleResponseVoResult = feeRuleFeignClient.calculateOrderFee(feeRuleRequestForm);

        FeeRuleResponseVo feeRuleResponseVo = feeRuleResponseVoResult.getData();
        //封装vo层
        ExpectOrderVo expectOrderVo = new ExpectOrderVo();

        expectOrderVo.setDrivingLineVo(drivingLineVo);
        expectOrderVo.setFeeRuleResponseVo(feeRuleResponseVo);

        return expectOrderVo;

    }

    @Override
    public Long submitOrder(SubmitOrderForm submitOrderForm) {
        //防抖操作
        Integer value1 = (Integer) redisTemplate.opsForValue().get("submitOrder:hasOrder:" + submitOrderForm.getCustomerId());
        if (value1 != null){
            throw new GuiguException(ResultCodeEnum.REPEAT_SUBMIT);
        }

        redisTemplate.opsForValue().set("submitOrder:hasOrder:"+submitOrderForm.getCustomerId(),1,60, TimeUnit.SECONDS);



        //根据乘客id判断有没有订单
        Boolean hasOrder = false;

        CurrentOrderInfoVo currentOrderInfoVo = searchCustomerCurrentOrder(submitOrderForm.getCustomerId());
        //如果状态是1,2,3,4,5,6就不可以下单

        Integer[] statusArray = {
                OrderStatus.ACCEPTED.getStatus(),
                OrderStatus.DRIVER_ARRIVED.getStatus(),
                OrderStatus.START_SERVICE.getStatus(),
                OrderStatus.END_SERVICE.getStatus(),
                OrderStatus.UPDATE_CART_INFO.getStatus()
        };
        for (Integer i : statusArray) {
            if (currentOrderInfoVo.getStatus()==null){
                break;
            }
            if (currentOrderInfoVo.getStatus().equals(i)){
                hasOrder = true;
            }
        }
        if (hasOrder){
            throw new GuiguException(ResultCodeEnum.REPEAT_SUBMIT);
        }




        //重新计算驾驶路线
        CalculateDrivingLineForm calculateDrivingLineForm = new CalculateDrivingLineForm();

        BeanUtils.copyProperties(submitOrderForm,calculateDrivingLineForm);

        Result<DrivingLineVo> drivingLineVoResult = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm);

        DrivingLineVo drivingLineVo = drivingLineVoResult.getData();

        //重新计算金额
        FeeRuleRequestForm calculateFeeRuleRequestForm = new FeeRuleRequestForm();
        calculateFeeRuleRequestForm.setDistance(drivingLineVo.getDistance());
        calculateFeeRuleRequestForm.setStartTime(new Date());
        calculateFeeRuleRequestForm.setWaitMinute(0);

        Result<FeeRuleResponseVo> feeRuleResponseVoResult = feeRuleFeignClient.calculateOrderFee(calculateFeeRuleRequestForm);
        FeeRuleResponseVo feeRuleResponseVo = feeRuleResponseVoResult.getData();

        //封装数据
        OrderInfoForm orderInfoForm = new OrderInfoForm();
        BeanUtils.copyProperties(submitOrderForm,orderInfoForm);
        orderInfoForm.setExpectDistance(drivingLineVo.getDistance());
        orderInfoForm.setExpectAmount(feeRuleResponseVo.getTotalAmount());
        Result<Long> orderInfoResult = orderInfoFeignClient.saveOrderInfo(orderInfoForm);


        Long orderId = orderInfoResult.getData();

        //通过任务调度: 查询附件可以接单司机
        NewOrderTaskVo newOrderDispatchVo = new NewOrderTaskVo();
        newOrderDispatchVo.setOrderId(orderId);
        newOrderDispatchVo.setStartLocation(orderInfoForm.getStartLocation());
        newOrderDispatchVo.setStartPointLongitude(orderInfoForm.getStartPointLongitude());
        newOrderDispatchVo.setStartPointLatitude(orderInfoForm.getStartPointLatitude());
        newOrderDispatchVo.setEndLocation(orderInfoForm.getEndLocation());
        newOrderDispatchVo.setEndPointLongitude(orderInfoForm.getEndPointLongitude());
        newOrderDispatchVo.setEndPointLatitude(orderInfoForm.getEndPointLatitude());
        newOrderDispatchVo.setExpectAmount(orderInfoForm.getExpectAmount());
        newOrderDispatchVo.setExpectDistance(orderInfoForm.getExpectDistance());
        newOrderDispatchVo.setExpectTime(drivingLineVo.getDuration());
        newOrderDispatchVo.setFavourFee(orderInfoForm.getFavourFee());
        newOrderDispatchVo.setCreateTime(new Date());
        Long jobId = newOrderFeignClient.addAndStartTask(newOrderDispatchVo).getData();

        redisTemplate.opsForValue().set("submitOrder:hasOrder:"+submitOrderForm.getCustomerId(),1,60, TimeUnit.SECONDS);

        return orderId;

    }

    @Override
    public Integer getOrderStatus(Long orderId) {

        Result<Integer> integerStatus = orderInfoFeignClient.getOrderStatus(orderId);

        return integerStatus.getData();
    }
    //查找乘客端当前订单
    @Override
    public CurrentOrderInfoVo searchCustomerCurrentOrder(Long userId) {

         return orderInfoFeignClient.searchCustomerCurrentOrder(userId).getData();
    }

    @Override
    public OrderInfoVo getOrderInfo(Long orderId, Long customerId) {

        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();

        if (orderInfo.getCustomerId() != customerId){
            throw new GuiguException(ResultCodeEnum.ILLEGAL_REQUEST);
        }

        //获取司机信息
        DriverInfoVo driverInfoVo = null;
        Long driverId = orderInfo.getDriverId();
        if (driverId!=null){
            driverInfoVo = driverInfoFeignClient.getDriverInfo(driverId).getData();
        }
        //获取账单信息
        OrderBillVo orderBillVo = null;
        if (orderInfo.getStatus()>=OrderStatus.UNPAID.getStatus()){
            orderBillVo = orderInfoFeignClient.getOrderBillInfo(orderId).getData();
        }

        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setOrderId(orderInfo.getId());
        BeanUtils.copyProperties(orderInfo,orderInfoVo);
        orderInfoVo.setDriverInfoVo(driverInfoVo);
        orderInfoVo.setOrderBillVo(orderBillVo);
        return orderInfoVo;

    }
    @Resource
    DriverInfoFeignClient driverInfoFeignClient;
    @Override
    public DriverInfoVo getDriverInfo(Long orderId, Long customerId) {
        //根据订单id获取订单的信息
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();
        if (orderInfo.getCustomerId()!=customerId){
            throw new GuiguException(ResultCodeEnum.DATA_ERROR);
        }

        return driverInfoFeignClient.getDriverInfo(orderInfo.getDriverId()).getData();

    }
    @Resource
    LocationFeignClient locationFeignClient;
    @Override
    public OrderLocationVo getCacheOrderLocation(Long orderId) {
        return locationFeignClient.getCacheOrderLocatin(orderId).getData();
    }

    @Override
    public DrivingLineVo calculateDrivingLine(CalculateDrivingLineForm calculateDrivingLineForm) {
        return mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();
    }

    @Override
    public OrderServiceLastLocationVo getOrderServiceLastLocation(Long orderId) {

        return locationFeignClient.getOrderServiceLastLocation(orderId).getData();
    }

    @Override
    public PageVo findCustomerOrderPage(Long customerId, Long page, Long limit) {
        return orderInfoFeignClient.findCustomerOrderPage(customerId,page,limit).getData();
    }

    @Override
    public WxPrepayVo createWxPayment(CreateWxPaymentForm createWxPaymentForm) {

        WxPrepayVo wxPrepayVo = new WxPrepayVo();
        wxPrepayVo.setTimeStamp(String.valueOf(System.currentTimeMillis()));
        return wxPrepayVo;
    }

    @Override
    public Boolean queryPayStatus(String orderNo) {
        return orderInfoFeignClient.queryPayStatus(orderNo).getData();
    }
}
